package jnpf.controller;

import cn.xuyanwu.spring.file.storage.MockMultipartFile;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.common.exception.RagFlowException;
import jnpf.model.common.UpFileReq;
import jnpf.model.ragFlow.chunk.DeleteChunksRequest;
import jnpf.model.ragFlow.common.IdReq;
import jnpf.model.ragFlow.common.RagFlowApiResult;
import jnpf.model.ragFlow.know.CreateKnowReq;
import jnpf.model.ragFlow.know.DatasetResp;
import jnpf.service.*;
import jnpf.entity.*;
import jnpf.util.*;
import jnpf.model.knowmange.*;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.File;
import java.io.FileInputStream;
import java.util.*;

import jnpf.base.vo.PageListVO;
import jnpf.base.vo.PaginationVO;
import jnpf.base.vo.DownloadVO;
import jnpf.config.ConfigValueUtil;

import java.io.IOException;

import org.springframework.web.multipart.MultipartFile;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import cn.xuyanwu.spring.file.storage.FileInfo;
import lombok.Cleanup;
import jnpf.model.visualJson.config.HeaderModel;
import jnpf.base.model.ColumnDataModel;
import jnpf.base.util.VisualUtils;
import org.springframework.transaction.annotation.Transactional;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.List;
import java.util.Map;

/**
 * knowMange
 *
 * @版本： V3.5
 * @版权： 引迈信息技术有限公司（https://www.jnpfsoft.com）
 * @作者： JNPF开发平台组
 * @日期： 2025-05-19
 */
@Slf4j
@RestController
@Tag(name = "knowMange", description = "example")
@RequestMapping("/api/example/KnowMange")
public class KnowMangeController {
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private GeneraterSwapUtil generaterSwapUtil;

    @Autowired
    private UserProvider userProvider;

    @Autowired
    private KnowMangeService knowMangeService;

    @Autowired
    private FileMangeService fileMangeService;

    @Autowired
    private KnowFileMetadataService knowFileMetadataService;


    @Autowired
    private ConfigValueUtil configValueUtil;

    @Autowired
    private RagFlowKnowService ragFlowKnowService;
    @Autowired
    private RagFlowFileService ragFlowFileService;
    @Autowired
    private RagChunksService ragChunksService;
    @Autowired
    private KnowFileMangeService knowFileMangeService;
    @Autowired
    private ThemeFileService themeFileService;



    /**
     * 列表
     *
     * @param knowMangePagination
     * @return
     */
    @Operation(summary = "获取列表")
    @PostMapping("/getList")
    public ActionResult list(@RequestBody KnowMangePagination knowMangePagination) throws IOException {
        List<KnowMangeEntity> list = knowMangeService.getList(knowMangePagination);
        List<Map<String, Object>> realList = new ArrayList<>();
        for (KnowMangeEntity entity : list) {
            Map<String, Object> knowMangeMap = JsonUtil.entityToMap(entity);
            knowMangeMap.put("id", knowMangeMap.get("id"));
            //副表数据
            //子表数据
            List<FileMangeEntity> fileMangeList = knowMangeService.getFileMangeList(entity.getId(), knowMangePagination);
            knowMangeMap.put("tableField113", JsonUtil.getJsonToList(JsonUtil.getListToJsonArray(fileMangeList)));
            realList.add(knowMangeMap);
        }
        //数据转换
        realList = generaterSwapUtil.swapDataList(realList, KnowMangeConstant.getFormData(), KnowMangeConstant.getColumnData(), knowMangePagination.getModuleId(), false);

        //返回对象
        PageListVO vo = new PageListVO();
        vo.setList(realList);
        PaginationVO page = JsonUtil.getJsonToBean(knowMangePagination, PaginationVO.class);
        vo.setPagination(page);
        return ActionResult.success(vo);
    }

    /**
     * 创建
     *
     * @param knowMangeForm
     * @return
     */
    @PostMapping()
    @Operation(summary = "创建")
    @Transactional
    public ActionResult create(@RequestBody @Valid KnowMangeForm knowMangeForm) {
        String b = knowMangeService.checkForm(knowMangeForm, 0);
        if (StringUtil.isNotEmpty(b)) {
            return ActionResult.fail(b);
        }
        try {
            KnowMangeEntity knowMangeEntity = knowMangeService.saveOrUpdate(knowMangeForm, null, true);
            return ActionResult.success("创建成功");
        } catch (RagFlowException e) {
            return ActionResult.fail(e.getMessage());
        } catch (Exception e) {
            return ActionResult.fail("新增失败: " + e.getMessage());
        }
    }


    /**
     * 导出Excel
     *
     * @return
     */
    @Operation(summary = "导出Excel")
    @PostMapping("/Actions/Export")
    public ActionResult Export(@RequestBody KnowMangePagination knowMangePagination) throws IOException {
        if (StringUtil.isEmpty(knowMangePagination.getSelectKey())) {
            return ActionResult.fail("请选择导出字段");
        }
        List<KnowMangeEntity> list = knowMangeService.getList(knowMangePagination);
        List<Map<String, Object>> realList = new ArrayList<>();
        for (KnowMangeEntity entity : list) {
            Map<String, Object> knowMangeMap = JsonUtil.entityToMap(entity);
            knowMangeMap.put("id", knowMangeMap.get("id"));
            //副表数据
            //子表数据
            List<FileMangeEntity> fileMangeList = knowMangeService.getFileMangeList(entity.getId(), knowMangePagination);
            knowMangeMap.put("tableField113", JsonUtil.getJsonToList(JsonUtil.getListToJsonArray(fileMangeList)));
            realList.add(knowMangeMap);
        }
        //数据转换
        realList = generaterSwapUtil.swapDataList(realList, KnowMangeConstant.getFormData(), KnowMangeConstant.getColumnData(), knowMangePagination.getModuleId(), false);
        String[] keys = !StringUtil.isEmpty(knowMangePagination.getSelectKey()) ? knowMangePagination.getSelectKey() : new String[0];
        UserInfo userInfo = userProvider.get();
        DownloadVO vo = this.creatModelExcel(configValueUtil.getTemporaryFilePath(), realList, keys, userInfo);
        return ActionResult.success(vo);
    }

    /**
     * 导出表格方法
     */
    public DownloadVO creatModelExcel(String path, List<Map<String, Object>> list, String[] keys, UserInfo userInfo) {
        DownloadVO vo = DownloadVO.builder().build();
        List<ExcelExportEntity> entitys = new ArrayList<>();
        if (keys.length > 0) {
            ExcelExportEntity tableField113ExcelEntity = new ExcelExportEntity("设计子表", "tableField113");
            List<ExcelExportEntity> tableField113List = new ArrayList<>();
            for (String key : keys) {
                switch (key) {
                    case "name":
                        entitys.add(new ExcelExportEntity("名称", "name"));
                        break;
                    case "des":
                        entitys.add(new ExcelExportEntity("描述", "des"));
                        break;
                    case "amount":
                        entitys.add(new ExcelExportEntity("文件数量", "amount"));
                        break;
                    case "img":
                        entitys.add(new ExcelExportEntity("知识库图片", "img"));
                        break;
                    case "createuser":
                        entitys.add(new ExcelExportEntity("创建用户", "createuser"));
                        break;
                    case "createtime":
                        entitys.add(new ExcelExportEntity("创建时间", "createtime"));
                        break;
                    case "updatetime":
                        entitys.add(new ExcelExportEntity("更新时间", "updatetime"));
                        break;
                    case "updateuser":
                        entitys.add(new ExcelExportEntity("更新用户", "updateuser"));
                        break;
                    case "datasetid":
                        entitys.add(new ExcelExportEntity("rag数据集id", "datasetid"));
                        break;
                    case "status":
                        entitys.add(new ExcelExportEntity("状态", "status"));
                        break;
                    case "tableField113-name":
                        tableField113List.add(new ExcelExportEntity("名称", "name"));
                        break;
                    case "tableField113-datasetid":
                        tableField113List.add(new ExcelExportEntity("rag数据集id", "datasetid"));
                        break;
                    case "tableField113-blocks":
                        tableField113List.add(new ExcelExportEntity("分块数", "blocks"));
                        break;
                    case "tableField113-uptime":
                        tableField113List.add(new ExcelExportEntity("上传日期", "uptime"));
                        break;
                    case "tableField113-type":
                        tableField113List.add(new ExcelExportEntity("切片方法", "type"));
                        break;
                    case "tableField113-status":
                        tableField113List.add(new ExcelExportEntity("解析状态", "status"));
                        break;
                    case "tableField113-ragfileid":
                        tableField113List.add(new ExcelExportEntity("rag文件id", "ragfileid"));
                        break;
                    default:
                        break;
                }
            }
            if (tableField113List.size() > 0) {
                tableField113ExcelEntity.setList(tableField113List);
                entitys.add(tableField113ExcelEntity);
            }
        }

        ExportParams exportParams = new ExportParams(null, "表单信息");
        exportParams.setType(ExcelType.XSSF);
        try {
            @Cleanup Workbook workbook = new HSSFWorkbook();
            if (entitys.size() > 0) {
                if (list.size() == 0) {
                    list.add(new HashMap<>());
                }
                //去除空数据
                List<Map<String, Object>> dataList = new ArrayList<>();
                for (Map<String, Object> map : list) {
                    int i = 0;
                    for (String key : keys) {
                        //子表
                        if (key.toLowerCase().startsWith("tablefield")) {
                            String tableField = key.substring(0, key.indexOf("-"));
                            String field = key.substring(key.indexOf("-") + 1);
                            Object o = map.get(tableField);
                            if (o != null) {
                                List<Map<String, Object>> childList = (List<Map<String, Object>>) o;
                                for (Map<String, Object> childMap : childList) {
                                    if (childMap.get(field) != null) {
                                        i++;
                                    }
                                }
                            }
                        } else {
                            Object o = map.get(key);
                            if (o != null) {
                                i++;
                            }
                        }
                    }
                    if (i > 0) {
                        dataList.add(map);
                    }
                }
                //复杂表头-表头和数据处理
                ColumnDataModel columnDataModel = JsonUtil.getJsonToBean(KnowMangeConstant.getColumnData(), ColumnDataModel.class);
                List<HeaderModel> complexHeaderList = columnDataModel.getComplexHeaderList();
                if (!Objects.equals(columnDataModel.getType(), 3) && !Objects.equals(columnDataModel.getType(), 5)) {
                    entitys = VisualUtils.complexHeaderHandel(entitys, complexHeaderList);
                    dataList = VisualUtils.complexHeaderDataHandel(dataList, complexHeaderList);
                }

                workbook = ExcelExportUtil.exportExcel(exportParams, entitys, dataList);
            }
            String fileName = "表单信息" + DateUtil.dateNow("yyyyMMdd") + "_" + RandomUtil.uuId() + ".xlsx";
            MultipartFile multipartFile = ExcelUtil.workbookToCommonsMultipartFile(workbook, fileName);
            String temporaryFilePath = configValueUtil.getTemporaryFilePath();
            FileInfo fileInfo = FileUploadUtils.uploadFile(multipartFile, temporaryFilePath, fileName);
            vo.setName(fileInfo.getFilename());
            vo.setUrl(UploaderUtil.uploaderFile(fileInfo.getFilename() + "#" + "Temporary") + "&name=" + fileName);
        } catch (Exception e) {
            log.error("信息导出Excel错误:{}", e.getMessage());
            e.printStackTrace();
        }
        return vo;
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @DeleteMapping("/batchRemove")
    @Transactional
    @Operation(summary = "批量删除")
    public ActionResult batchRemove(@RequestBody String ids) {
        List<String> idList = JsonUtil.getJsonToList(ids, String.class);
        int i = 0;
        for (String allId : idList) {
            this.delete(allId);
            i++;
        }
        if (i == 0) {
            return ActionResult.fail("删除失败");
        }
        return ActionResult.success("删除成功");
    }

    /**
     * 编辑
     *
     * @param id
     * @param knowMangeForm
     * @return
     */
    @PutMapping("/{id}")
    @Operation(summary = "更新")
    @Transactional
    public ActionResult update(@PathVariable("id") String id, @RequestBody @Valid KnowMangeForm knowMangeForm, @RequestParam(value = "isImport", required = false) boolean isImport) {
        knowMangeForm.setId(id);
        if (!isImport) {
            String b = knowMangeService.checkForm(knowMangeForm, 1);
            if (StringUtil.isNotEmpty(b)) {
                return ActionResult.fail(b);
            }
        }
        KnowMangeEntity entity = knowMangeService.getInfo(id);
        if (entity != null) {
            try {
                knowMangeService.saveOrUpdate(knowMangeForm, id, false);
                if (!isImport) {
                    //更新数据集
                    CreateKnowReq createDataSetsReq = ragFlowKnowService.getCreateKnowReq(knowMangeForm);
                    RagFlowApiResult dataset = ragFlowKnowService.updateDataset(createDataSetsReq, entity.getDatasetid());
                }
            } catch (Exception e) {
                return ActionResult.fail("修改数据失败");
            }
            return ActionResult.success("更新成功");
        } else {
            return ActionResult.fail("更新失败，数据不存在");
        }
    }

    @Operation(summary = "上传文件到rag")
    @PostMapping("/uploadFiles2/{id}")
    public ActionResult<String> uploadFiles2(@RequestBody List<UpFileReq> file, @PathVariable("id") String id) {
        // 先获取 KnowMangeEntity 数据
        KnowMangeEntity info = knowMangeService.getById(id);
        if (info == null) {
            return ActionResult.fail("知识库不存在");
        }
        String path = jnpf.util.FileUploadUtils.getLocalBasePath() + configValueUtil.getWebAnnexFilePath();

        // 将UpFileReq转换为MultipartFile，并保留url信息
        List<MultipartFile> multipartFiles = new ArrayList<>();
        Map<String, String> fileUrlMap = new HashMap<>(); // 用于存储文件名到url的映射
        for (UpFileReq req : file) {
            try {
                File fileObj = new File(path + req.getFileId());
                MultipartFile multipartFile = new MockMultipartFile(
                        req.getName(),
                        req.getName(),
                        "text/plain",
                        new FileInputStream(fileObj)
                );
                multipartFiles.add(multipartFile);
                // 存储文件名到url的映射
                fileUrlMap.put(req.getName(), req.getUrl());
            } catch (IOException e) {
                log.error("文件转换失败", e);
                return ActionResult.fail("文件转换失败：" + e.getMessage());
            }
        }

        // 调用uploadFiles方法，并传递url映射
        return this.uploadFiles(multipartFiles, id, fileUrlMap);
    }

    @Operation(summary = "上传文件到rag")
    @PostMapping("/uploadFiles/{id}")
    public ActionResult<String> uploadFiles(@RequestParam("file") List<MultipartFile> file, @PathVariable("id") String id) {
        // 调用原始的uploadFiles方法，没有url映射（用于传统表单上传）
        return this.uploadFiles(file, id, null);
    }

    // 私有方法：处理文件上传的核心逻辑
    private ActionResult<String> uploadFiles(List<MultipartFile> file, String id, Map<String, String> fileUrlMap) {
        // 先获取 KnowMangeEntity 数据
        KnowMangeEntity info = knowMangeService.getById(id);
        if (info == null) {
            return ActionResult.fail("知识库不存在");
        }
        if (file.isEmpty()) {
            return ActionResult.fail("请选择文件");
        }
        try {
            // 更新 amount 文件数量字段
            Integer currentAmount = info.getAmount();
            if (currentAmount == null) {
                currentAmount = 0;
            }
            int newAmount = currentAmount + file.size();
            info.setAmount(newAmount);
            knowMangeService.updateById(info);

            // 调用RAG服务上传文件
            RagFlowApiResult ragFlowApiResult = ragFlowFileService.uploadFiles(info.getDatasetid(), file);
            if (ragFlowApiResult.getCode() != 0) {
                return ActionResult.fail("文件上传失败：" + ragFlowApiResult.getMessage());
            }

            // 使用 Gson 替代 ObjectMapper
            Gson gson = new Gson();
            String jsonString = gson.toJson(ragFlowApiResult.getData());
            List<Map<String, Object>> fileDataList = gson.fromJson(jsonString, new TypeToken<List<Map<String, Object>>>() {
            }.getType());

            // 检查文件数量是否匹配
            if (fileDataList.size() != file.size()) {
                log.warn("上传的文件数量与返回的文件数量不匹配：上传{}个，返回{}个", file.size(), fileDataList.size());
            }

            // 处理每个上传的文件
            for (Map<String, Object> fileData : fileDataList) {
                String ragFileId = (String) fileData.get("id");
                String fileType = (String) fileData.get("type");
                String fileName = (String) fileData.get("name");

                if (ragFileId == null || fileType == null || fileName == null) {
                    log.error("文件数据不完整，缺少id、type或name字段: {}", fileData);
                    continue; // 跳过有问题的文件
                }

                // 创建并保存文件管理实体
                KnowFileMangeEntity entity = new KnowFileMangeEntity();
                entity.setName(fileName);
                entity.setBlocks(0);
                entity.setUptime(new Date());
                entity.setType(fileType);
                entity.setStatus("1");
                entity.setCreatetime(new Date());
                entity.setUpdateuser(userProvider.get().getId());
                entity.setDatasetid(info.getDatasetid());
                entity.setHandle("0");
                entity.setRagfileid(ragFileId);
                entity.setKnowid(id);

                // 设置localurl字段
                if (fileUrlMap != null && fileUrlMap.containsKey(fileName)) {
                    entity.setLocalurl(fileUrlMap.get(fileName));
                } else {
                    log.warn("无法找到文件 {} 的URL信息", fileName);
                    // 可以设置默认值或保持null
                }

                knowFileMangeService.save(entity);
            }
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return ActionResult.fail("上传文件失败：" + e.getMessage());
        }

        return ActionResult.success("文件上传成功");
    }

    /**
     * 删除
     *
     * @param id
     * @return
     */
    @Operation(summary = "删除")
    @DeleteMapping("/{id}")
    @Transactional
    public ActionResult delete(@PathVariable("id") String id) {
        KnowMangeEntity entity = knowMangeService.getInfo(id);
        if (entity != null) {
            //主表数据删除
            knowMangeService.delete(entity);

            //1. 删除本地file_mange数据
            QueryWrapper<FileMangeEntity> queryWrapperFileMange = new QueryWrapper<>();
            queryWrapperFileMange.lambda().eq(FileMangeEntity::getKnowid, entity.getId());
            List<FileMangeEntity> fileList = fileMangeService.list(queryWrapperFileMange);
            fileMangeService.remove(queryWrapperFileMange);

            //2. 删除本地file_metadata数据
            QueryWrapper<KnowFileMetadataEntity> queryWrapperKnowFileMetadata = new QueryWrapper<>();
            queryWrapperKnowFileMetadata.lambda().eq(KnowFileMetadataEntity::getDatasetid, entity.getId());
            List<KnowFileMetadataEntity> metadataList = knowFileMetadataService.list(queryWrapperKnowFileMetadata);
            knowFileMetadataService.remove(queryWrapperKnowFileMetadata);

            //3、主题文件关联删除
            ArrayList<String> fileId = new ArrayList<>();
            //主题关联文件删除
            fileList.forEach(file -> {
                fileId.add(file.getId());
            });
            if (!fileId.isEmpty()) {
                QueryWrapper<ThemeFileEntity> queryWrapperThemeFile = new QueryWrapper<>();
                queryWrapperThemeFile.lambda().in(ThemeFileEntity::getFileid, fileId);
                themeFileService.remove(queryWrapperThemeFile);
            }

            //RAG相关删除逻辑
            String datasetid = entity.getDatasetid();
            if (StringUtil.isNotEmpty(datasetid)) {
                try {
                    //1. 删除RAG知识库
                    ragFlowKnowService.deleteDataset(new IdReq(datasetid));

                    //2. 删除RAG文件列表（修改为使用datasetId参数）
                    for (FileMangeEntity file : fileList) {
                        if (StringUtil.isNotEmpty(file.getRagfileid())) {
                            ragFlowFileService.deleteDocuments(datasetid, new IdReq(file.getRagfileid()));
                        }
                    }

                    //3. 删除RAG数据块（修改为使用datasetId和DeleteChunksRequest参数）
//                    for (KnowFileMetadataEntity metadata : metadataList) {
//                        if (StringUtil.isNotEmpty(metadata.getRagdataid())) {
//                            DeleteChunksRequest deleteRequest = new DeleteChunksRequest();
//                            deleteRequest.setChunk_ids(Collections.singletonList(metadata.getRagdataid()));
//                            ragChunksService.deleteChunks(datasetid, metadata.getRagfileid(), deleteRequest);
//                        }
//                    }
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return ActionResult.success("删除成功");
    }

    /**
     * 表单信息(详情页)
     * 详情页面使用-转换数据
     *
     * @param id
     * @return
     */
    @Operation(summary = "表单信息(详情页)")
    @GetMapping("/detail/{id}")
    public ActionResult detailInfo(@PathVariable("id") String id) {
        KnowMangeEntity entity = knowMangeService.getInfo(id);
        if (entity == null) {
            return ActionResult.fail("表单数据不存在！");
        }
        Map<String, Object> knowMangeMap = JsonUtil.entityToMap(entity);
        knowMangeMap.put("id", knowMangeMap.get("id"));
        //副表数据
        //子表数据
        List<FileMangeEntity> fileMangeList = knowMangeService.getFileMangeList(entity.getId());
        knowMangeMap.put("tableField113", JsonUtil.getJsonToList(JsonUtil.getListToJsonArray(fileMangeList)));
        knowMangeMap = generaterSwapUtil.swapDataDetail(knowMangeMap, KnowMangeConstant.getFormData(), "691935090543974853", false);
        return ActionResult.success(knowMangeMap);
    }

    /**
     * 获取详情(编辑页)
     * 编辑页面使用-不转换数据
     *
     * @param id
     * @return
     */
    @Operation(summary = "信息")
    @GetMapping("/{id}")
    public ActionResult info(@PathVariable("id") String id) {
        KnowMangeEntity entity = knowMangeService.getInfo(id);
        if (entity == null) {
            return ActionResult.fail("表单数据不存在！");
        }
        Map<String, Object> knowMangeMap = JsonUtil.entityToMap(entity);
        knowMangeMap.put("id", knowMangeMap.get("id"));
        //副表数据
        //子表数据
        List<FileMangeEntity> fileMangeList = knowMangeService.getFileMangeList(entity.getId());
        knowMangeMap.put("fileMangeList", JsonUtil.getJsonToList(JsonUtil.getListToJsonArray(fileMangeList)));
        knowMangeMap = generaterSwapUtil.swapDataForm(knowMangeMap, KnowMangeConstant.getFormData(), KnowMangeConstant.TABLEFIELDKEY, KnowMangeConstant.TABLERENAMES);
        return ActionResult.success(knowMangeMap);
    }


}
